<!DOCTYPE html>
<html prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article# " lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>python-network-scripting-pp4e | 绿萝间</title>
<link href="../assets/css/all-nocdn.css" rel="stylesheet" type="text/css">
<link href="../assets/css/ipython.min.css" rel="stylesheet" type="text/css">
<link href="../assets/css/nikola_ipython.css" rel="stylesheet" type="text/css">
<meta name="theme-color" content="#5670d4">
<meta name="generator" content="Nikola (getnikola.com)">
<link rel="alternate" type="application/rss+xml" title="RSS" href="../rss.xml">
<link rel="canonical" href="https://muxuezi.github.io/posts/python-network-scripting-pp4e.html">
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
    tex2jax: {
        inlineMath: [ ['$','$'], ["\\(","\\)"] ],
        displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
        processEscapes: true
    },
    displayAlign: 'center', // Change this to 'center' to center equations.
    "HTML-CSS": {
        styles: {'.MathJax_Display': {"margin": 0}}
    }
});
</script><!--[if lt IE 9]><script src="../assets/js/html5.js"></script><![endif]--><meta name="author" content="Tao Junjie">
<link rel="prev" href="introduction-to-julia.html" title="introduction-to-julia" type="text/html">
<link rel="next" href="kivy-ch5-remote-desktop-app.html" title="kivy-ch5-remote-desktop-app" type="text/html">
<meta property="og:site_name" content="绿萝间">
<meta property="og:title" content="python-network-scripting-pp4e">
<meta property="og:url" content="https://muxuezi.github.io/posts/python-network-scripting-pp4e.html">
<meta property="og:description" content="Network Scripting in Programming Python, 4th Edition, This chapter introduces Internet fundamentals and explores sockets, the underlying communications mechanism of the Internet.









Plumbing the">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2015-06-24T13:44:27+08:00">
<meta property="article:tag" content="CHS">
<meta property="article:tag" content="ipython">
<meta property="article:tag" content="Other">
<meta property="article:tag" content="Python">
</head>
<body>
<a href="#content" class="sr-only sr-only-focusable">Skip to main content</a>

<!-- Menubar -->

<nav class="navbar navbar-inverse navbar-static-top"><div class="container">
<!-- This keeps the margins nice -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-navbar" aria-controls="bs-navbar" aria-expanded="false">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="https://muxuezi.github.io/">

                <span id="blog-title">绿萝间</span>
            </a>
        </div>
<!-- /.navbar-header -->
        <div class="collapse navbar-collapse" id="bs-navbar" aria-expanded="false">
            <ul class="nav navbar-nav">
<li>
<a href="../archive.html">Archive</a>
                </li>
<li>
<a href="../categories/">Tags</a>
                </li>
<li>
<a href="../rss.xml">RSS feed</a>

                
            </li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
    <a href="python-network-scripting-pp4e.ipynb" id="sourcelink">Source</a>
    </li>

                
            </ul>
</div>
<!-- /.navbar-collapse -->
    </div>
<!-- /.container -->
</nav><!-- End of Menubar --><div class="container" id="content" role="main">
    <div class="body-content">
        <!--Body content-->
        <div class="row">
            
            
<article class="post-text h-entry hentry postpage" itemscope="itemscope" itemtype="http://schema.org/Article"><header><h1 class="p-name entry-title" itemprop="headline name"><a href="#" class="u-url">python-network-scripting-pp4e</a></h1>

        <div class="metadata">
            <p class="byline author vcard"><span class="byline-name fn">
                    Tao Junjie
            </span></p>
            <p class="dateline"><a href="#" rel="bookmark"><time class="published dt-published" datetime="2015-06-24T13:44:27+08:00" itemprop="datePublished" title="2015-06-24 13:44">2015-06-24 13:44</time></a></p>
            
        <p class="sourceline"><a href="python-network-scripting-pp4e.ipynb" id="sourcelink">Source</a></p>

        </div>
        

    </header><div class="e-content entry-content" itemprop="articleBody text">
    <div tabindex="-1" id="notebook" class="border-box-sizing">
    <div class="container" id="notebook-container">

<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Network Scripting in <a href="http://www.rmi.net/~lutz/about-pp4e.html">Programming Python, 4th Edition</a>, This chapter introduces Internet fundamentals and explores sockets, the underlying communications mechanism of the Internet.</p>
<!-- TEASER_END -->
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Plumbing-the-Internet">Plumbing the Internet<a class="anchor-link" href="python-network-scripting-pp4e.html#Plumbing-the-Internet">¶</a>
</h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="The-Socket-Layer">The Socket Layer<a class="anchor-link" href="python-network-scripting-pp4e.html#The-Socket-Layer">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In simple terms, sockets are a programmable interface to connections between pro-
grams, possibly running on different computers of a network. They allow data format-
ted as byte strings to be passed between processes and machines. Sockets also form the
basis and low-level “plumbing” of the Internet itself: all of the familiar higher-level Net
protocols, like FTP, web pages, and email, ultimately occur over sockets. Sockets are
also sometimes called communications endpoints because they are the portals through
which programs send and receive bytes during a conversation.</p>
<p>socket的英文原义是“孔”或“插座”，通常也称作"套接字"，用于描述IP地址和端口，是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件，同时提供几种服务。每种服务都打开一个Socket，并绑定到一个端口上，不同的端口对应于不同的服务。Socket正如其英文原意那样，象一个多孔插座。一台主机犹如布满各种插座的房间，每个插座有一个编号，有的插座提供220伏交流电， 有的提供110伏交流电，有的则提供有线电视节目。 客户软件将插头插到不同编号的插座，就可以得到不同的服务。</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Although often used for network conversations, sockets may also be used as a com-
munication mechanism between programs running on the same computer, taking the
form of a general Inter-Process Communication (IPC) mechanism. We saw this socket
usage mode briefly in Chapter 5. Unlike some IPC devices, sockets are bidirectional
data streams: programs may both send and receive data through them.</p>
<p>也可IPC，双向数据</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>To programmers, sockets take the form of a handful of calls available in a library. These
socket calls know how to send bytes between machines, using lower-level operations
such as the TCP network transmission control protocol. At the bottom, TCP knows
how to transfer bytes, but it doesn’t care what those bytes mean. For the purposes of
this text, we will generally ignore how bytes sent to sockets are physically transferred.
To understand sockets fully, though, we need to know a bit about how computers are
named.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Machine-identifiers">Machine identifiers<a class="anchor-link" href="python-network-scripting-pp4e.html#Machine-identifiers">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ul>
<li>Machine identifiers = Machine names(IP address) + Port numbers(0..1023) </li>
<li>domain name server = {domain name : IP address}</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="The-Protocol-Layer">The Protocol Layer<a class="anchor-link" href="python-network-scripting-pp4e.html#The-Protocol-Layer">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Python provides support for standard protocols, which auto-
mates most of the socket and message formatting details.
Standard Internet protocols define a structured way to talk over sockets. 
They generally standardize both message formats and socket port numbers:</p>
<ul>
<li>Message formats provide structure for the bytes exchanged over sockets during
conversations.</li>
<li>Port numbers are reserved numeric identifiers for the underlying sockets over which
messages are exchanged.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Port-number-rules">Port number rules<a class="anchor-link" href="python-network-scripting-pp4e.html#Port-number-rules">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>make it easier for programs to locate the standard protocols,
port numbers in the range of 0 to 1023 are reserved and preassigned to the standard
higher-level protocols.</p>
<table border="1" cellspacing="0" cellpadding="0" width="100%" style="width:100.0%;
 mso-cellspacing:0in;mso-padding-alt:0in 0in 0in 0in"><tbody>
<tr>
<td colspan="4" style="border:none;padding:.75pt .75pt .75pt .75pt">
  <h6 align="center" style="text-align:center"><a name="_Toc6690727">Table 12-1.
  Port Numbers Reserved for Common Protocols</a></h6>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p align="center" style="text-align:center"><b><span style="font-size:10.0pt">Protocol<p></p></span></b></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p align="center" style="text-align:center"><b><span style="font-size:10.0pt">Common
  Function<p></p></span></b></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p align="center" style="text-align:center"><b><span style="font-size:10.0pt">Port
  Number<p></p></span></b></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p align="center" style="text-align:center"><b><span style="font-size:10.0pt">Python
  Module<p></p></span></b></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">HTTP<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Web pages<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">80<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>http.client , http.server</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">NNTP<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Usenet news<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">119<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>nntplib</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">FTP data default<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">File transfers<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">20<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>ftplib</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">FTP control<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">File transfers<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">21<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>ftplib</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">SMTP<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Sending email<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">25<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>smtplib</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">POP3<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Fetching email<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">110<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>poplib</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">IMAP4<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Fetching email<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">143<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>imaplib</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Finger<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Informational<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">79<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">n/a<p></p></span></p>
  </td>
 </tr>
<tr>
<td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Telnet<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">Command lines <p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><span style="font-size:10.0pt">23<p></p></span></p>
  </td>
  <td style="padding:.75pt .75pt .75pt .75pt">
  <p><tt><span style='font-size:10.0pt;font-family:"Courier New"'>telnetlib</span></tt><span style="font-size:10.0pt"><p></p></span></p>
  </td>
 </tr>
</tbody></table>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Clients-and-servers">Clients and servers<a class="anchor-link" href="python-network-scripting-pp4e.html#Clients-and-servers">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>On one side of a conversation, machines that support standard
protocols perpetually run a set of programs that listen for connection requests on the
reserved ports. On the other end of a dialog, other machines contact those programs
to use the services they export.
We usually call the perpetually running listener program a server and the connecting
program a client. Let’s use the familiar web browsing model as an example. As shown
in Table 12-1, the HTTP protocol used by the Web allows clients and servers to talk
over sockets on port 80:</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Server</p>
<ul>
<li>A machine that hosts websites usually runs a web server program that constantly
listens for incoming connection requests, on a socket bound to port 80. Often, the
server itself does nothing but watch for requests on its port perpetually; handling
requests is delegated to spawned processes or threads.</li>
</ul>
<p>Clients</p>
<ul>
<li>Programs that wish to talk to this server specify the server machine’s name and
port 80 to initiate a connection. For web servers, typical clients are web browsers
like Firefox, Internet Explorer, or Chrome, but any script can open a client-side
connection on port 80 to fetch web pages from the server. The server’s machine
name can also be simply “localhost” if it’s the same as the client’s.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Protocol-structures">Protocol structures<a class="anchor-link" href="python-network-scripting-pp4e.html#Protocol-structures">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The structure of those message bytes varies from protocol to protocol, is hidden
by the Python library. For example, the FTP protocol prevents deadlock by conversing over two sockets: one
for control messages only and one to transfer file data. An FTP server listens for control
messages (e.g., “send me a file”) on one port, and transfers file data over another. FTP
clients open socket connections to the server machine’s control port, send requests,
and send or receive file data over a socket connected to a data port on the server machine. FTP also defines standard message structures passed between client and server.
The control message used to request a file, for instance, must follow a standard format.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Python’s-Internet-Library-Modules">Python’s Internet Library Modules<a class="anchor-link" href="python-network-scripting-pp4e.html#Python%E2%80%99s-Internet-Library-Modules">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In fact, each supported protocol is represented in Python’s standard library by either a
module package of the same name as the protocol or by a module file with a name of
the form xxxlib.py</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Socket-Programming">Socket Programming<a class="anchor-link" href="python-network-scripting-pp4e.html#Socket-Programming">¶</a>
</h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Although sockets them-
selves transfer only byte strings, we can also transfer Python objects through them by
using Python’s pickle module. Because this module converts Python objects such as
lists, dictionaries, and class instances to and from byte strings, it provides the extra step
needed to ship higher-level objects through sockets when required.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Beyond basic data communication tasks, the socket module also includes a variety of
more advanced tools. For instance, it has calls for the following and more:</p>
<ul>
<li>Converting bytes to a standard network ordering ( ntohl , htonl )</li>
<li>Querying machine name and address ( gethostname , gethostbyname )</li>
<li>Wrapping socket objects in a file object interface ( sockobj.makefile )</li>
<li>Making socket calls nonblocking ( sockobj.setblocking )</li>
<li>Setting socket timeouts ( sockobj.settimeout )</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Socket-Basics">Socket Basics<a class="anchor-link" href="python-network-scripting-pp4e.html#Socket-Basics">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Server side: open a TCP/IP socket on a port, listen for a message from
a client, and send an echo reply; this is a simple one-shot listen/reply
conversation per client, but it goes into an infinite loop to listen for
more clients as long as this server script runs; the client may run on
a remote machine, or on same computer if it uses 'localhost' for server</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [8]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>
<span class="n">myHost</span> <span class="o">=</span> <span class="s1">''</span>                                               <span class="c1"># '' = all available interfaces on host</span>
<span class="n">myPort</span> <span class="o">=</span> <span class="mi">50007</span>                                        <span class="c1"># listen on a non-reserved port number</span>
<span class="n">sockobj</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="c1">#make a TCP socket object</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span><span class="p">))</span>                 <span class="c1">#bind it to server port number</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>                                         <span class="c1">#listen, allow 5 pending connects</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
    <span class="n">connections</span><span class="p">,</span> <span class="n">address</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span> <span class="c1">#wait for next client connect</span>
    <span class="nb">print</span> <span class="s1">'Server connected by'</span><span class="p">,</span> <span class="n">address</span>       <span class="c1">#connection is a new socket</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">connections</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>            <span class="c1"># read next line on client socket</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span> <span class="k">break</span>                                <span class="c1"># send a reply line to the client</span>
        <span class="n">connections</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Echo =&gt;'</span> <span class="o">+</span> <span class="n">data</span><span class="p">)</span>   <span class="c1"># until eof when socket closed</span>
    <span class="n">connections</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Client side: use sockets to send data to the server, and print server's
reply to each message line; 'localhost' means that the server is running
on the same machine as the client, which lets us test client and server
on one machine; to test over the Internet, run a server on a remote
machine, and set serverHost or argv[1] to machine's domain name or IP addr;
Python sockets are a portable BSD socket interface, with object methods
for the standard socket calls available in the system's C library;</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [17]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>
<span class="n">serverHost</span> <span class="o">=</span> <span class="s1">'localhost'</span> <span class="c1"># portable socket interface plus constants </span>
                                      <span class="c1"># server name, or: 'starship.python.net'</span>
<span class="n">serverPort</span> <span class="o">=</span> <span class="mi">50007</span>        <span class="c1"># non-reserved port used by the server</span>
<span class="n">message</span> <span class="o">=</span> <span class="p">[</span><span class="sa">b</span><span class="s1">'Hello network world'</span><span class="p">]</span> <span class="c1"># default text to send to server</span>
                                                        <span class="c1"># requires bytes: b'' or str,encode()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
    <span class="n">serverHost</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>              <span class="c1"># server from cmd line arg 1</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">:</span>                      <span class="c1"># text from cmd line args 2..n</span>
        <span class="n">message</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">encode</span><span class="p">()</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">:])</span> 
        
<span class="n">sockobj</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="c1"># make a TCP/IP socket object</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">serverHost</span><span class="p">,</span> <span class="n">serverPort</span><span class="p">))</span> <span class="c1"># connect to server machine + port</span>

<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">message</span><span class="p">:</span>
    <span class="n">sockobj</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>                   <span class="c1"># send line to server over socket</span>
    <span class="n">data</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>       <span class="c1"># receive line from server: up to 1k</span>
    <span class="nb">print</span> <span class="s1">'Client received:'</span><span class="p">,</span> <span class="n">data</span>     <span class="c1"># bytes are quoted, was `x`, repr(x)</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Server-socket-calls">Server socket calls<a class="anchor-link" href="python-network-scripting-pp4e.html#Server-socket-calls">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Uses the Python socket module to create a TCP socket object. The names
AF_INET and SOCK_STREAM are preassigned variables defined by and imported from
the socket module; using them in combination means “create a TCP/IP socket,”
the standard communication device for the Internet. More specifically, AF_INET
means the IP address protocol, and SOCK_STREAM means the TCP transfer protocol.
The AF_INET / SOCK_STREAM combination is the default because it is so common, but
it’s typical to make this explicit.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [24]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sockobj</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Associates the socket object with an address—for IP addresses, we pass a server
machine name and port number on that machine. This is where the server identifies
the machine and port associated with the socket. In server programs, the hostname
is typically an empty string (“”), which means the machine that the script runs on
(formally, all available local and remote interfaces on the machine), and the port
is a number outside the range 0 to 1023 (which is reserved for standard protocols,
described earlier).
Note that each unique socket dialog you support must have its own port number;
if you try to open a socket on a port already in use, Python will raise an exception.
Also notice the nested parentheses in this call—for the AF_INET address protocol
socket here, we pass the host/port socket address to bind as a two-item tuple object
(pass a string for AF_UNIX ). Te</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [25]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sockobj</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span><span class="p">))</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Starts listening for incoming client connections and allows for a backlog of up to
five pending requests. The value passed sets the number of incoming client requests
queued by the operating system before new requests are denied (which happens
only if a server isn’t fast enough to process requests before the queues fill up). A
value of 5 is usually enough for most socket-based programs; the value must be at
least 1.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [31]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sockobj</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>At this point, the server is ready to accept connection requests from client programs
running on remote machines (or the same machine) and falls into an infinite loop—
while True (or the equivalent while 1 for older Pythons and ex-C programmers)—
waiting for them to arrive:</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">connection</span><span class="p">,</span> <span class="n">address</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Waits for the next client connection request to occur; when it does, the accept call
returns a brand-new socket object over which data can be transferred from and to
the connected client. Connections are accepted on sockobj , but communication
with a client happens on connection , the new socket. This call actually returns a
two-item tuple— address is the connecting client’s Internet address. We can call
accept more than one time, to service multiple client connections; that’s why each
call returns a new, distinct socket for talking to a particular client.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Once we have a client connection, we fall into another loop to receive data from the
client in blocks of up to 1,024 bytes at a time, and echo each block back to the client:</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [33]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">data</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Reads at most 1,024 more bytes of the next message sent from a client (i.e., coming
across the network or IPC connection), and returns it to the script as a byte string.
We get back an empty byte string when the client has finished—end-of-file is triggered when the client closes its end of the socket.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [35]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">connection</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Echo=&gt;'</span> <span class="o">+</span> <span class="n">data</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Sends the latest byte string data block back to the client program, prepending the
string 'Echo=&gt;' to it first. The client program can then recv what we send here—
the next reply line. Technically this call sends as much data as possible, and returns
the number of bytes actually sent. To be fully robust, some programs may need to
resend unsent portions or use connection.sendall to force all bytes to be sent.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Transferring-byte-strings-and-objects">Transferring byte strings and objects<a class="anchor-link" href="python-network-scripting-pp4e.html#Transferring-byte-strings-and-objects">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Although the socket model is limited to transferring byte strings, you can
send and receive nearly arbitrary Python objects with the standard library pickle object
serialization module. Its dumps and loads calls convert Python objects to and from byte
strings, ready for direct socket transfer:</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [36]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">pickle</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [38]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">dumps</span><span class="p">([</span><span class="mi">99</span><span class="p">,</span><span class="mi">100</span><span class="p">])</span>       <span class="c1"># on sending end... convert to byte strings</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [41]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">x</span>                                              <span class="c1"># string passed to send, returned by recv</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt output_prompt">Out[41]:</div>


<div class="output_text output_subarea output_execute_result">
<pre>'(lp0\nI99\naI100\na.'</pre>
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [42]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">pickle</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>                         <span class="c1"># on receiving end... convert back to object</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt output_prompt">Out[42]:</div>


<div class="output_text output_subarea output_execute_result">
<pre>[99, 100]</pre>
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>For simpler types that correspond to those in the C language, the struct module provides the byte-string conversion we need as well:</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [43]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">struct</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [44]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s1">'&gt;ii'</span><span class="p">,</span> <span class="mi">99</span> <span class="p">,</span><span class="mi">100</span><span class="p">)</span>      <span class="c1"># convert simpler types for transmission</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [45]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">x</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt output_prompt">Out[45]:</div>


<div class="output_text output_subarea output_execute_result">
<pre>'\x00\x00\x00c\x00\x00\x00d'</pre>
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [48]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s1">'&gt;ii'</span><span class="p">,</span><span class="n">x</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt output_prompt">Out[48]:</div>


<div class="output_text output_subarea output_execute_result">
<pre>(99, 100)</pre>
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Client-socket-calls">Client socket calls<a class="anchor-link" href="python-network-scripting-pp4e.html#Client-socket-calls">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [50]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sockobj</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">serverHost</span><span class="p">,</span> <span class="n">serverPort</span><span class="p">))</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Opens a connection to the machine and port on which the server program is lis-
tening for client connections. This is where the client specifies the string name of
the service to be contacted. In the client, we can either specify the name of the
remote machine as a domain name (e.g., starship.python.net) or numeric IP ad-
dress. We can also give the server name as localhost (or the equivalent IP address
127.0.0.1 ) to specify that the server program is running on the same machine as
the client; that comes in handy for debugging servers without having to connect
to the Net. And again, the client’s port number must match the server’s exactly.
Note the nested parentheses again—just as in server bind calls, we really pass the
server’s host/port address to connect in a tuple object.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Once the client establishes a connection to the server, it falls into a loop, sending a
message one line at a time and printing whatever the server sends back after each line
is sent:</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sockobj</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Transfers the next byte-string message line to the server over the socket. Notice
that the default list of lines contains bytes strings ( b'...' ). Just as on the server,
data passed through the socket must be a byte string, though it can be the result
of a manual str.encode encoding call or an object conversion with pickle or
struct if desired. When lines to be sent are given as command-line arguments
instead, they must be converted from str to bytes ; the client arranges this by en-
coding in a generator expression (a call map(str.encode, sys.argv[2:]) would have
the same effect).</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Running-Socket-Programs-Locally">Running Socket Programs Locally<a class="anchor-link" href="python-network-scripting-pp4e.html#Running-Socket-Programs-Locally">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The server keeps
running and responds to requests made each time you run the client script in the other
window.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Running-Socket-Programs-Remotely">Running Socket Programs Remotely<a class="anchor-link" href="python-network-scripting-pp4e.html#Running-Socket-Programs-Remotely">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>First, upload the server’s source file to a remote machine where
you have an account and a Python.
The &amp; syntax in Unix/Linux shells can be used to run the server
script in the background.
Now that the server is listening for connections on the Net, run the client on your local
computer multiple times again. This time, the client runs on a different machine than
the server, so we pass in the server’s domain or IP name as a client command-line
argument. The server still uses a machine name of "" because it always listens on what-
ever machine it runs on.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [51]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="o">!</span>ping learning-python.com
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>PING learning-python.com (97.74.215.115) 56(84) bytes of data.
64 bytes from p3nlh266.shr.prod.phx3.secureserver.net (97.74.215.115): icmp_seq=1 ttl=38 time=210 ms
64 bytes from p3nlh266.shr.prod.phx3.secureserver.net (97.74.215.115): icmp_seq=2 ttl=38 time=212 ms
64 bytes from p3nlh266.shr.prod.phx3.secureserver.net (97.74.215.115): icmp_seq=3 ttl=38 time=214 ms
64 bytes from p3nlh266.shr.prod.phx3.secureserver.net (97.74.215.115): icmp_seq=4 ttl=38 time=209 ms
64 bytes from p3nlh266.shr.prod.phx3.secureserver.net (97.74.215.115): icmp_seq=5 ttl=38 time=217 ms
^C
--- learning-python.com ping statistics ---
6 packets transmitted, 5 received, 16% packet loss, time 5004ms
rtt min/avg/max/mdev = 209.249/212.888/217.931/3.055 ms

</pre>
</div>
</div>

</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Socket-pragmatics">Socket pragmatics<a class="anchor-link" href="python-network-scripting-pp4e.html#Socket-pragmatics">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ol>
<li>you can run the client and server like this on any two Internet-aware machines where Python is installed. All you need then is a computer that allows sockets, and most do.</li>
<li>the socket module generally raises exceptions if you ask for something invalid.</li>
<li>be sure to kill the server process before restarting it again, or else the port number will still be in use, and you’ll get another exception.</li>
</ol>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Spawning-Clients-in-Parallel">Spawning Clients in Parallel<a class="anchor-link" href="python-network-scripting-pp4e.html#Spawning-Clients-in-Parallel">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [52]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">PP4E.launchmodes</span> <span class="k">import</span> <span class="n">QuietPortableLauncher</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [53]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">numclients</span> <span class="o">=</span> <span class="mi">8</span>
<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="n">cmdline</span><span class="p">):</span>
    <span class="n">QuietPortableLauncher</span><span class="p">(</span><span class="n">cmdline</span><span class="p">,</span> <span class="n">cmdline</span><span class="p">)()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [54]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># start('echo-server.py')                     # spawn server locally if not yet started</span>
<span class="n">args</span> <span class="o">=</span> <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>               <span class="c1"># pass server name if running remotely</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">numclients</span><span class="p">):</span>
    <span class="n">start</span><span class="p">(</span><span class="s1">'echo-client.py </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="n">args</span><span class="p">)</span>  <span class="c1"># spawn 8? clients to test the server</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Talking-to-Reserved-Ports">Talking to Reserved Ports<a class="anchor-link" href="python-network-scripting-pp4e.html#Talking-to-Reserved-Ports">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>It’s also important to know that this client and server engage in a proprietary sort of
discussion, and so use the port number 50007 outside the range reserved for standard
protocols (0 to 1023). There’s nothing preventing a client from opening a socket on
one of these special ports, however. For instance, the following client-side code con-
nects to programs listening on the standard email, FTP, and HTTP web server ports
on three different server machines:</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [56]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h5 id="talk-to-POP-email-server">talk to POP email server<a class="anchor-link" href="python-network-scripting-pp4e.html#talk-to-POP-email-server">¶</a>
</h5>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [57]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [58]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="s1">'pop.secureserver.net'</span><span class="p">,</span> <span class="mi">110</span><span class="p">))</span> 
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [59]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">print</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">70</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>+OK &lt;28789.1401261144@p3plpop05-10.prod.phx3.secureserver.net&gt;

</pre>
</div>
</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [60]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h5 id="talk-to-FTP-server">talk to FTP server<a class="anchor-link" href="python-network-scripting-pp4e.html#talk-to-FTP-server">¶</a>
</h5>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [63]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [64]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="s1">'learning-python.com'</span><span class="p">,</span> <span class="mi">21</span><span class="p">))</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [65]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">print</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">70</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre>220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You
</pre>
</div>
</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [60]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h5 id="talk-to-Python's-HTTP-server">talk to Python's HTTP server<a class="anchor-link" href="python-network-scripting-pp4e.html#talk-to-Python's-HTTP-server">¶</a>
</h5>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [78]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [79]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="s1">'www.python.net'</span><span class="p">,</span> <span class="mi">80</span><span class="p">))</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [80]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s1">'GET /</span><span class="se">\r\n</span><span class="s1">'</span><span class="p">)</span> <span class="c1"># fetch root page reply</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt output_prompt">Out[80]:</div>


<div class="output_text output_subarea output_execute_result">
<pre>7</pre>
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [81]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">70</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt output_prompt">Out[81]:</div>


<div class="output_text output_subarea output_execute_result">
<pre>'&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r\n    "http://'</pre>
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [82]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">70</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt output_prompt">Out[82]:</div>


<div class="output_text output_subarea output_execute_result">
<pre>'www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;\r\n&lt;html xmlns="http://www.'</pre>
</div>

</div>

</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [84]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Python’s poplib , ftplib , and http.client and urllib.request modules provide
higher-level interfaces for talking to servers on these ports.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Binding-reserved-port-servers">Binding reserved port servers<a class="anchor-link" href="python-network-scripting-pp4e.html#Binding-reserved-port-servers">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Speaking of reserved ports, it’s all right to open client-side connections on reserved
ports as in the prior section, but you can’t install your own server-side scripts for these
ports unless you have special permission.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [86]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [88]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="s1">''</span><span class="p">,</span><span class="mi">80</span><span class="p">))</span>
</pre></div>

</div>
</div>
</div>

<div class="output_wrapper">
<div class="output">


<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_text output_error">
<pre>
<span class="ansi-red-intense-fg ansi-bold">---------------------------------------------------------------------------</span>
<span class="ansi-red-intense-fg ansi-bold">error</span>                                     Traceback (most recent call last)
<span class="ansi-green-intense-fg ansi-bold">&lt;ipython-input-88-0c574f672e0b&gt;</span> in <span class="ansi-cyan-fg">&lt;module&gt;</span><span class="ansi-blue-intense-fg ansi-bold">()</span>
<span class="ansi-green-intense-fg ansi-bold">----&gt; 1</span><span class="ansi-yellow-intense-fg ansi-bold"> </span>sock<span class="ansi-yellow-intense-fg ansi-bold">.</span>bind<span class="ansi-yellow-intense-fg ansi-bold">(</span><span class="ansi-yellow-intense-fg ansi-bold">(</span><span class="ansi-blue-intense-fg ansi-bold">''</span><span class="ansi-yellow-intense-fg ansi-bold">,</span><span class="ansi-cyan-intense-fg ansi-bold">80</span><span class="ansi-yellow-intense-fg ansi-bold">)</span><span class="ansi-yellow-intense-fg ansi-bold">)</span>

<span class="ansi-green-intense-fg ansi-bold">/usr/lib/python2.7/socket.pyc</span> in <span class="ansi-cyan-fg">meth</span><span class="ansi-blue-intense-fg ansi-bold">(name, self, *args)</span>
<span class="ansi-green-fg">    222</span> 
<span class="ansi-green-fg">    223</span> <span class="ansi-green-intense-fg ansi-bold">def</span> meth<span class="ansi-yellow-intense-fg ansi-bold">(</span>name<span class="ansi-yellow-intense-fg ansi-bold">,</span>self<span class="ansi-yellow-intense-fg ansi-bold">,</span><span class="ansi-yellow-intense-fg ansi-bold">*</span>args<span class="ansi-yellow-intense-fg ansi-bold">)</span><span class="ansi-yellow-intense-fg ansi-bold">:</span>
<span class="ansi-green-intense-fg ansi-bold">--&gt; 224</span><span class="ansi-yellow-intense-fg ansi-bold">     </span><span class="ansi-green-intense-fg ansi-bold">return</span> getattr<span class="ansi-yellow-intense-fg ansi-bold">(</span>self<span class="ansi-yellow-intense-fg ansi-bold">.</span>_sock<span class="ansi-yellow-intense-fg ansi-bold">,</span>name<span class="ansi-yellow-intense-fg ansi-bold">)</span><span class="ansi-yellow-intense-fg ansi-bold">(</span><span class="ansi-yellow-intense-fg ansi-bold">*</span>args<span class="ansi-yellow-intense-fg ansi-bold">)</span>
<span class="ansi-green-fg">    225</span> 
<span class="ansi-green-fg">    226</span> <span class="ansi-green-intense-fg ansi-bold">for</span> _m <span class="ansi-green-intense-fg ansi-bold">in</span> _socketmethods<span class="ansi-yellow-intense-fg ansi-bold">:</span>

<span class="ansi-red-intense-fg ansi-bold">error</span>: [Errno 13] Permission denied</pre>
</div>
</div>

</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Handling-Multiple-Clients">Handling Multiple Clients<a class="anchor-link" href="python-network-scripting-pp4e.html#Handling-Multiple-Clients">¶</a>
</h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In real-world client/server programs, it’s far more typical to code a server so as to avoid
blocking new requests while handling a current client’s request. Perhaps the easiest
way to do so is to service each client’s request in parallel—in a new process, in a new
thread, or by manually switching (multiplexing) between clients in an event loop. This
isn’t a socket issue per se, and we already learned how to start processes and threads
in Chapter 5. But since these schemes are so typical of socket server programming, let’s
explore all three ways to handle client requests in parallel here.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Forking-Servers">Forking Servers<a class="anchor-link" href="python-network-scripting-pp4e.html#Forking-Servers">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Server side: open a socket on a port, listen for a message from a client,
and send an echo reply; forks a process to handle each client connection;
child processes share parent's socket descriptors; fork is less portable
than threads--not yet on Windows, unless Cygwin or similar installed</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [92]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>
<span class="n">myHost</span> <span class="o">=</span> <span class="s1">''</span>                                               <span class="c1"># '' = all available interfaces on host</span>
<span class="n">myPort</span> <span class="o">=</span> <span class="mi">50007</span>                                        <span class="c1"># listen on a non-reserved port number</span>

<span class="n">sockobj</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="c1">#make a TCP socket object</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span><span class="p">))</span>                 <span class="c1">#bind it to server port number</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>                                         <span class="c1">#listen, allow 5 pending connects</span>

<span class="k">def</span> <span class="nf">now</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">ctime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span>

<span class="n">activeChildren</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">reapChildren</span><span class="p">():</span>                                        <span class="c1"># reap any dead child processes</span>
    <span class="k">while</span> <span class="n">activeChildren</span><span class="p">:</span>                                 <span class="c1"># else may fill up system table</span>
        <span class="n">pid</span><span class="p">,</span> <span class="n">stat</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">waitpid</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">WNOHANG</span><span class="p">)</span> <span class="c1"># don't hang if no child exited</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">pid</span><span class="p">:</span> <span class="k">break</span>
        <span class="n">activeChildren</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span>

<span class="c1"># child process: reply, exit simulate a blocking activity</span>
<span class="c1"># read, write a client socket till eof when socket closed        </span>
<span class="k">def</span> <span class="nf">handleClient</span><span class="p">(</span><span class="n">connection</span><span class="p">):</span>
    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">connections</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>            <span class="c1"># read next line on client socket</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span> <span class="k">break</span>                                <span class="c1"># send a reply line to the client</span>
        <span class="n">reply</span> <span class="o">=</span> <span class="s1">'Echo=&gt;</span><span class="si">%s</span><span class="s1"> at </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="n">now</span><span class="p">())</span>
        <span class="n">connections</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">reply</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>       <span class="c1"># until eof when socket closed</span>
    <span class="n">connections</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
    <span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">dispatcher</span><span class="p">():</span>                                               <span class="c1"># listen until process killed </span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>                                                    <span class="c1"># wait for next connection,</span>
        <span class="n">connection</span><span class="p">,</span> <span class="n">address</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>      <span class="c1"># pass to process for service</span>
        <span class="nb">print</span> <span class="s1">'Server connected by'</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="s1">'at'</span><span class="p">,</span> <span class="n">now</span><span class="p">()</span>
        <span class="n">reapChildren</span><span class="p">()</span>                                          <span class="c1"># clean up exited children now</span>
        <span class="n">childPid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fork</span><span class="p">()</span>                                    <span class="c1"># copy this process</span>
        <span class="k">if</span> <span class="n">childPid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>                                        <span class="c1"># if in child process: handle</span>
            <span class="n">handleClient</span><span class="p">(</span><span class="n">connection</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>                                                          <span class="c1"># else: go accept next connect</span>
            <span class="n">activeChildren</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">childPid</span><span class="p">)</span>             <span class="c1"># add to active child pid list</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [96]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dispatcher</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Running-the-forking-server">Running the forking server<a class="anchor-link" href="python-network-scripting-pp4e.html#Running-the-forking-server">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="o">!</span>netstat -pant <span class="p">|</span> grep <span class="m">50007</span> #show <span class="m">50007</span> port
<span class="o">!</span><span class="nb">kill</span> -9 pid                             # <span class="nb">kill</span> python server
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>the test proceeds as follows:</p>
<ol>
<li>The server starts running remotely.</li>
<li>All three clients are started and connect to the server a few seconds apart.</li>
<li>On the server, the client requests trigger three forked child processes, which all
immediately go to sleep for five seconds (to simulate being busy doing something
useful).</li>
<li>Each client waits until the server replies, which happens five seconds after their
initial requests.</li>
</ol>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In a more realistic application, that delay could be fatal if many clients were trying to
connect at once—the server would be stuck in the action we’re simulating with
time.sleep , and not get back to the main loop to accept new client requests. With
process forks per request, clients can be serviced in parallel.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Killing-dead-but-listed-child-processes-zombies">Killing dead-but-listed child processes zombies<a class="anchor-link" href="python-network-scripting-pp4e.html#Killing-dead-but-listed-child-processes-zombies">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>ps -af full process listing command shows that all the dead child pro-
cesses stay in the system process table (show as <defunct> )</defunct></p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>When the reapChildren command is reactivated, dead child zombie entries are cleaned
up each time the server gets a new client connection request, by calling the Python
os.waitpid function. A few zombies may accumulate if the server is heavily loaded, but
they will remain only until the next client connection is received (you get only as many
zombies as processes served in parallel since the last accept )</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In fact, if you type fast enough, you can actually see a child process morph from a real
running program into a zombie. Here, for example, a child spawned to handle a new
request changes to <defunct> on exit. Its connection cleans up lingering zombies, and
its own process entry will be removed completely when the next request is received.</defunct></p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Preventing-zombies-with-signal-handlers-on-Linux">Preventing zombies with signal handlers on Linux<a class="anchor-link" href="python-network-scripting-pp4e.html#Preventing-zombies-with-signal-handlers-on-Linux">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>On some systems, it’s also possible to clean up zombie child processes by resetting the
signal handler for the SIGCHLD signal delivered to a parent process by the operating
system when a child process stops or exits. If a Python script assigns the SIG_IGN (ignore)
action as the SIGCHLD signal handler, zombies will be removed automatically and im-
mediately by the operating system as child processes exit; the parent need not issue
wait calls to clean up after them. Because of that, this scheme is a simpler alternative
to manually reaping zombies on platforms where it is supported.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [1]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># Demo Python's signal module; pass signal number as a command-line arg, and use</span>
<span class="c1"># a "kill -N pid" shell command to send this process a signal; on my Linux machine,</span>
<span class="c1"># SIGUSR1=10, SIGUSR2=12, SIGCHLD=17, and SIGCHLD handler stays in effect even if</span>
<span class="c1"># not restored: all other handlers are restored by Python after caught, but SIGCHLD</span>
<span class="c1"># behavior is left to the platform's implementation; signal works on Windows too,</span>
<span class="c1"># but defines only a few signal types; signals are not very portable in general</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [4]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">signal</span><span class="o">,</span> <span class="nn">time</span>
<span class="k">def</span> <span class="nf">now</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">asctime</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">onSignal</span><span class="p">(</span><span class="n">signum</span><span class="p">,</span> <span class="n">stackframe</span><span class="p">):</span>              <span class="c1"># Python signal handler</span>
    <span class="nb">print</span> <span class="s1">'Got signal'</span><span class="p">,</span> <span class="n">signum</span><span class="p">,</span> <span class="s1">'at'</span><span class="p">,</span> <span class="n">now</span><span class="p">()</span>
    <span class="c1"># most handlers stay in effect but sigchld handler is not</span>
    <span class="k">if</span> <span class="n">signum</span> <span class="o">==</span> <span class="n">signal</span><span class="o">.</span><span class="n">SIGCHLD</span><span class="p">:</span>                <span class="c1">#signal.signal(signal.SIGCHLD, onSignal)</span>
        <span class="nb">print</span> <span class="s1">'sigchld caught'</span>

<span class="n">signum</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">signal</span><span class="o">.</span><span class="n">signal</span><span class="p">(</span><span class="n">signum</span><span class="p">,</span> <span class="n">onSignal</span><span class="p">)</span>                 <span class="c1"># install signal handler</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">signal</span><span class="o">.</span><span class="n">pause</span><span class="p">()</span>                         <span class="c1"># sleep waiting for signals</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>To run this script, simply put it in the background and send it signals by typing the
kill -signal-number process-id shell command line; this is the shell’s equivalent of
Python’s os.kill function available on Unix-like platforms only. Process IDs are listed
in the PID column of ps command results. Here is this script in action catching signal
numbers 10 (reserved for general use) and 9 (the unavoidable terminate signal).</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [5]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>
<span class="n">myHost</span> <span class="o">=</span> <span class="s1">''</span>                                               <span class="c1"># '' = all available interfaces on host</span>
<span class="n">myPort</span> <span class="o">=</span> <span class="mi">50007</span>                                        <span class="c1"># listen on a non-reserved port number</span>

<span class="n">sockobj</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="c1">#make a TCP socket object</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span><span class="p">))</span>                 <span class="c1">#bind it to server port number</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>                                         <span class="c1">#listen, allow 5 pending connects</span>
<span class="n">signal</span><span class="o">.</span><span class="n">signal</span><span class="p">(</span><span class="n">signal</span><span class="o">.</span><span class="n">SIGCHLD</span><span class="p">,</span> <span class="n">signal</span><span class="o">.</span><span class="n">SIG_IGN</span><span class="p">)</span> <span class="c1">#avoid child zombie processes</span>

<span class="k">def</span> <span class="nf">now</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">ctime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span>

<span class="c1"># child process: reply, exit simulate a blocking activity</span>
<span class="c1"># read, write a client socket till eof when socket closed        </span>
<span class="k">def</span> <span class="nf">handleClient</span><span class="p">(</span><span class="n">connection</span><span class="p">):</span>
    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">connections</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>            <span class="c1"># read next line on client socket</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span> <span class="k">break</span>                                <span class="c1"># send a reply line to the client</span>
        <span class="n">reply</span> <span class="o">=</span> <span class="s1">'Echo=&gt;</span><span class="si">%s</span><span class="s1"> at </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">data</span><span class="p">,</span><span class="n">now</span><span class="p">())</span>
        <span class="n">connections</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">reply</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>       <span class="c1"># until eof when socket closed</span>
    <span class="n">connections</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
    <span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">dispatcher</span><span class="p">():</span>                                               <span class="c1"># listen until process killed </span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>                                                    <span class="c1"># wait for next connection,</span>
        <span class="n">connection</span><span class="p">,</span> <span class="n">address</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>      <span class="c1"># pass to process for service</span>
        <span class="nb">print</span> <span class="s1">'Server connected by'</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="s1">'at'</span><span class="p">,</span> <span class="n">now</span><span class="p">()</span>
        <span class="n">childPid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fork</span><span class="p">()</span>                                    <span class="c1"># copy this process</span>
        <span class="k">if</span> <span class="n">childPid</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>                                        <span class="c1"># if in child process: handle</span>
            <span class="n">handleClient</span><span class="p">(</span><span class="n">connection</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ol>
<li>Much simpler; we don’t need to manually track or reap child processes.</li>
<li>More accurate; it leaves no zombies temporarily between client requests.</li>
</ol>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>this technique is not universally supported across
all flavors of Unix. If you care about portability, manually reaping children as we did
in Example 12-4 may still be desirable.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Why-multiprocessing-doesn’t-help-with-socket-server-portability">Why multiprocessing doesn’t help with socket server portability<a class="anchor-link" href="python-network-scripting-pp4e.html#Why-multiprocessing-doesn%E2%80%99t-help-with-socket-server-portability">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Though it's crash on Win,open sockets are not correctly
pickled when passed as arguments into the new process, it's ok on linux.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Threading-Servers">Threading Servers<a class="anchor-link" href="python-network-scripting-pp4e.html#Threading-Servers">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Because threads all run in the same process and memory space, they automatically share
sockets passed between them, similar in spirit to the way that child processes inherit
socket descriptors. Unlike processes, though, threads are usually less expensive to start,
and work on both Unix-like machines and Windows under standard Python today.
Furthermore, many (though not all) see threads as simpler to program—child threads
die silently on exit, without leaving behind zombies to haunt the server.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># Server side: open a socket on a port, listen for a message from a client,</span>
<span class="c1"># and send an echo reply; echoes lines until eof when client closes socket;</span>
<span class="c1"># spawns a thread to handle each client connection; threads share global</span>
<span class="c1"># memory space with main thread; this is more portable than fork: threads</span>
<span class="c1"># work on standard Windows systems, but process forks do not</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">_thread</span> <span class="k">as</span> <span class="nn">thread</span>           <span class="c1"># or use threading.Thread().start()</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>                     <span class="c1"># get socket constructor and constants</span>
<span class="n">myHost</span> <span class="o">=</span> <span class="s1">''</span>                              <span class="c1"># server machine, '' means local host</span>
<span class="n">myPort</span> <span class="o">=</span> <span class="mi">50007</span>                           <span class="c1"># listen on a non-reserved port number</span>

<span class="n">sockobj</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span>           <span class="c1"># make a TCP socket object</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span><span class="p">))</span>                   <span class="c1"># bind it to server port number</span>
<span class="n">sockobj</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>                                <span class="c1"># allow up to 5 pending connects</span>

<span class="k">def</span> <span class="nf">now</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">ctime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span>               <span class="c1"># current time on the server</span>

<span class="k">def</span> <span class="nf">handleClient</span><span class="p">(</span><span class="n">connection</span><span class="p">):</span>                    <span class="c1"># in spawned thread: reply</span>
    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>                                <span class="c1"># simulate a blocking activity</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>                                  <span class="c1"># read, write a client socket</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">connection</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span> <span class="k">break</span>
        <span class="n">reply</span> <span class="o">=</span> <span class="s1">'Echo=&gt;</span><span class="si">%s</span><span class="s1"> at </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">now</span><span class="p">())</span>
        <span class="n">connection</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">reply</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
    <span class="n">connection</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">dispatcher</span><span class="p">():</span>                                <span class="c1"># listen until process killed</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>                                  <span class="c1"># wait for next connection,</span>
        <span class="n">connection</span><span class="p">,</span> <span class="n">address</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>   <span class="c1"># pass to thread for service</span>
        <span class="nb">print</span> <span class="s1">'Server connected by'</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="s1">'at'</span><span class="p">,</span> <span class="n">now</span><span class="p">()</span>
        <span class="n">thread</span><span class="o">.</span><span class="n">start_new_thread</span><span class="p">(</span><span class="n">handleClient</span><span class="p">,</span> <span class="p">(</span><span class="n">connection</span><span class="p">,))</span>

<span class="n">dispatcher</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Remember that a thread silently exits when the function it is running returns; unlike
the process fork version, we don’t call anything like os . _exit in the client handler func-
tion (and we shouldn’t—it may kill all threads in the process, including the main loop
watching for new connections!). Because of this, the thread version is not only more
portable, but also simpler.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Standard-Library-Server-Classes">Standard Library Server Classes<a class="anchor-link" href="python-network-scripting-pp4e.html#Standard-Library-Server-Classes">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>socketserver module defines classes that implement all flavors of forking and threading
servers that you are likely to be interested in.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="sd">"""</span>
<span class="sd">Server side: open a socket on a port, listen for a message from a client, and </span>
<span class="sd">send an echo reply; this version uses the standard library module socketserver to</span>
<span class="sd">do its work; socketserver provides TCPServer, ThreadingTCPServer, ForkingTCPServer,</span>
<span class="sd">UDP variants of these, and more, and routes each client connect request to a new </span>
<span class="sd">instance of a passed-in request handler object's handle method; socketserver also</span>
<span class="sd">supports Unix domain sockets, but only on Unixen; see the Python library manual.</span>
<span class="sd">"""</span>

<span class="kn">import</span> <span class="nn">SocketServer</span> <span class="k">as</span> <span class="nn">socketserver</span><span class="o">,</span> <span class="nn">time</span>               <span class="c1"># get socket server, handler objects</span>
<span class="n">myHost</span> <span class="o">=</span> <span class="s1">''</span>                             <span class="c1"># server machine, '' means local host</span>
<span class="n">myPort</span> <span class="o">=</span> <span class="mi">50007</span>                          <span class="c1"># listen on a non-reserved port number</span>
<span class="k">def</span> <span class="nf">now</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">ctime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span>

<span class="k">class</span> <span class="nc">MyClientHandler</span><span class="p">(</span><span class="n">socketserver</span><span class="o">.</span><span class="n">BaseRequestHandler</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>                           <span class="c1"># on each client connect</span>
        <span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">client_address</span><span class="p">,</span> <span class="n">now</span><span class="p">())</span>       <span class="c1"># show this client's address</span>
        <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>                           <span class="c1"># simulate a blocking activity</span>
        <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>                             <span class="c1"># self.request is client socket</span>
            <span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>      <span class="c1"># read, write a client socket</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span> <span class="k">break</span>
            <span class="n">reply</span> <span class="o">=</span> <span class="s1">'Echo=&gt;</span><span class="si">%s</span><span class="s1"> at </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">now</span><span class="p">())</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">reply</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

<span class="c1"># make a threaded server, listen/handle clients forever</span>
<span class="n">myaddr</span> <span class="o">=</span> <span class="p">(</span><span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span><span class="p">)</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">socketserver</span><span class="o">.</span><span class="n">ThreadingTCPServer</span><span class="p">(</span><span class="n">myaddr</span><span class="p">,</span> <span class="n">MyClientHandler</span><span class="p">)</span>
<span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Multiplexing-Servers-with-select">Multiplexing Servers with select<a class="anchor-link" href="python-network-scripting-pp4e.html#Multiplexing-Servers-with-select">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Technically, though, threads and processes don’t really run in parallel, unless you’re
lucky enough to have a machine with many CPUs. Instead, your operating system
performs a juggling act—it divides the computer’s processing power among all active
tasks. It runs part of one, then part of another, and so on. All the tasks appear to run
in parallel, but only because the operating system switches focus between tasks so fast
that you don’t usually notice. This process of switching between tasks is sometimes
called time-slicing when done by an operating system; it is more generally known as
multiplexing.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In select-asynchronous servers, a single main
loop run in a single process and thread decides which clients should get a bit of attention
each time through. Client requests and the main dispatcher loop are each given a small
slice of the server’s attention if they are ready to converse.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>That is, when the sources passed to select are sockets, we can be sure that socket calls like accept , recv , and send will not
block (pause) the server when applied to objects returned by select . Because of that,
a single-loop server that uses select need not get stuck communicating with one client
or waiting for new ones while other clients are starved for the server’s attention.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Because this type of server does not need to start threads or processes, it can be efficient
when transactions with clients are relatively short-lived. However, it also requires that
these transactions be quick; if they are not, it still runs the risk of becoming bogged
down waiting for a dialog with a particular client to end, unless augmented with threads
or forks for long-running transactions.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Confusingly, select-based servers are often called asynchronous, to describe their multiplexing of short-lived transactions. 
Really, though, the classic forking and threading servers we met earlier are asynchronous, too,
as they do not wait for completion of a given client’s request. 
There is a clearer distinction between serial and parallel servers</p>
<ul>
<li>{“synchronous”: “serial, process one transaction at a time”,  “asynchronous” : “parallel” }</li>
<li>forking, threading, and select loops are three alternative ways to implement parallel, asynchronous servers.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="A-select-based-echo-server">A select-based echo server<a class="anchor-link" href="python-network-scripting-pp4e.html#A-select-based-echo-server">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>can handle multiple clients without ever starting new
processes or threads</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># P822</span>
<span class="sd">"""</span>
<span class="sd">Server: handle multiple clients in parallel with select. use the select</span>
<span class="sd">module to manually multiplex among a set of sockets: main sockets which</span>
<span class="sd">accept new client connections, and input sockets connected to accepted</span>
<span class="sd">clients; select can take an optional 4th arg--0 to poll, n.m to wait n.m</span>
<span class="sd">seconds, or omitted to wait till any socket is ready for processing.</span>
<span class="sd">"""</span>

<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">select</span> <span class="k">import</span> <span class="n">select</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="n">socket</span><span class="p">,</span> <span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span>


<span class="k">def</span> <span class="nf">now</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">ctime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span>

<span class="n">myHost</span> <span class="o">=</span> <span class="s1">''</span>                             <span class="c1"># server machine, '' means local host</span>
<span class="n">myPort</span> <span class="o">=</span> <span class="mi">50007</span>                          <span class="c1"># listen on a non-reserved port number</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>                  <span class="c1"># allow host/port as cmdline args too</span>
    <span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
<span class="n">numPortSocks</span> <span class="o">=</span> <span class="mi">2</span>                        <span class="c1"># number of ports for client connects</span>

<span class="c1"># make main sockets for accepting new client requests</span>
<span class="n">mainsocks</span><span class="p">,</span> <span class="n">readsocks</span><span class="p">,</span> <span class="n">writesocks</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[],</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">numPortSocks</span><span class="p">):</span>
    <span class="n">portsock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span>   <span class="c1"># make a TCP/IP socket object</span>
    <span class="n">portsock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">myHost</span><span class="p">,</span> <span class="n">myPort</span><span class="p">))</span>           <span class="c1"># bind it to server port number</span>
    <span class="n">portsock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>                              <span class="c1"># listen, allow 5 pending connects</span>
    <span class="n">mainsocks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">portsock</span><span class="p">)</span>                <span class="c1"># add to main list to identify</span>
    <span class="n">readsocks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">portsock</span><span class="p">)</span>                <span class="c1"># add to select inputs list</span>
    <span class="n">myPort</span> <span class="o">+=</span> <span class="mi">1</span>                               <span class="c1"># bind on consecutive ports</span>

<span class="c1"># event loop: listen and multiplex until server process killed</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'select-server loop starting'</span><span class="p">)</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
    <span class="c1"># print(readsocks)</span>
    <span class="n">readables</span><span class="p">,</span> <span class="n">writeables</span><span class="p">,</span> <span class="n">exceptions</span> <span class="o">=</span> <span class="n">select</span><span class="p">(</span><span class="n">readsocks</span><span class="p">,</span> <span class="n">writesocks</span><span class="p">,</span> <span class="p">[])</span>
    <span class="k">for</span> <span class="n">sockobj</span> <span class="ow">in</span> <span class="n">readables</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">sockobj</span> <span class="ow">in</span> <span class="n">mainsocks</span><span class="p">:</span>                     <span class="c1"># for ready input sockets</span>
            <span class="c1"># port socket: accept new client</span>
            <span class="n">newsock</span><span class="p">,</span> <span class="n">address</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>      <span class="c1"># accept should not block</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'Connect:'</span><span class="p">,</span> <span class="n">address</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">newsock</span><span class="p">))</span>  <span class="c1"># newsock is a new socket</span>
            <span class="n">readsocks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">newsock</span><span class="p">)</span>                <span class="c1"># add to select list, wait</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c1"># client socket: read next line</span>
            <span class="n">data</span> <span class="o">=</span> <span class="n">sockobj</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>                <span class="c1"># recv should not block</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\t</span><span class="s1">got'</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="s1">'on'</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">sockobj</span><span class="p">))</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span>                             <span class="c1"># if closed by the clients</span>
                <span class="n">sockobj</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>                      <span class="c1"># close here and remv from</span>
                <span class="n">readsocks</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">sockobj</span><span class="p">)</span>            <span class="c1"># del list else reselected</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># this may block: should really select for writes too</span>
                <span class="n">reply</span> <span class="o">=</span> <span class="s1">'Echo=&gt;</span><span class="si">%s</span><span class="s1"> at </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">now</span><span class="p">())</span>
                <span class="n">sockobj</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">reply</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Formally, select is called with three lists of selectable objects (input sources, out-
put sources, and exceptional condition sources), plus an optional timeout. The
timeout argument may be a real wait expiration value in seconds (use floating-point
numbers to express fractions of a second), a zero value to mean simply poll and
return immediately, or omitted to mean wait until at least one object is ready (as
done in our server script). The call returns a triple of ready objects—subsets of the
first three arguments—any or all of which may be empty if the timeout expired
before sources became ready.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>If you’re interested in using select , you will probably also be interested in checking
out the asyncore.py module in the standard Python library. It implements a class-
based callback model, where input and output callbacks are dispatched to class
methods by a precoded select event loop. As such, it allows servers to be con-
structed without threads or forks, and it is a select -based alternative to the sock
etserver module’s threading and forking module we met in the prior sections. As
for this type of server in general, asyncore is best when transactions are short—
what it describes as “I/O bound” instead of “CPU bound” programs, the latter of
which still require threads or forks. See the Python library manual for details and
a usage example.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Twisted">Twisted<a class="anchor-link" href="python-network-scripting-pp4e.html#Twisted">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>For other server options, see also the open source Twisted system (<a href="http://twistedmatrix.com">http://twistedmatrix.com</a>). Twisted is an asynchronous networking framework written in Python
that supports TCP, UDP, multicast, SSL/TLS, serial communication, and more. It
supports both clients and servers and includes implementations of a number of
commonly used network services such as a web server, an IRC chat server, a mail
server, a relational database interface, and an object broker.
Although Twisted supports processes and threads for longer-running actions, it
also uses an asynchronous, event-driven model to handle clients, which is similar
to the event loop of GUI libraries like tkinter. It abstracts an event loop, which
multiplexes among open socket connections, automates many of the details in-
herent in an asynchronous server, and provides an event-driven framework for
scripts to use to accomplish application tasks. Twisted’s internal event engine is
similar in spirit to our select -based server and the asyncore module, but it is re-
garded as much more advanced. Twisted is a third-party system, not a standard
library tool; see its website and documentation for more details.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Summary:-Choosing-a-Server-Scheme">Summary: Choosing a Server Scheme<a class="anchor-link" href="python-network-scripting-pp4e.html#Summary:-Choosing-a-Server-Scheme">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ol>
<li>
<p>select</p>
<ul>
<li>perform very well when client transactions are relatively short and are not CPU-bound.</li>
<li>split up the processing of a client’s request in such a
way that it can be multiplexed with other requests and not block the server’s main loop</li>
<li>select also seems more complex than spawning either processes or threads,
because we need to manually transfer control among all tasks (for instance, compare
the threaded and select versions of our echo server, even without write selects).</li>
</ul>
</li>
<li>
<p>threads or forks</p>
<ul>
<li>Threads and forks are especially useful if clients require
long-running processing above and beyond the socket calls used to pass data.</li>
</ul>
</li>
<li>
<p>The asyncore standard library module</p>
</li>
<li>Twisted</li>
</ol>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Making-Sockets-Look-Like-Files-and-Streams">Making Sockets Look Like Files and Streams<a class="anchor-link" href="python-network-scripting-pp4e.html#Making-Sockets-Look-Like-Files-and-Streams">¶</a>
</h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>allow a script to use standard stream tools such as the print and input built-in
functions and sys module file calls (e.g., sys.stdout.write ), and connect them to sock-
ets only when needed.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The socket object makefile method comes in handy anytime you wish to process a
socket with normal file object methods or need to pass a socket to an existing interface
or program that expects a file.</p>
<p>The makefile method also allows us to treat normally binary socket data as text instead
of byte strings, and has additional arguments such as encoding that let us specify non-
default Unicode encodings for the transferred text</p>
<p>Although text can always
be encoded and decoded with manual calls after binary mode socket transfers, make
file shifts the burden of text encodings from your code to the file wrapper object.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="A-Stream-Redirection-Utility">A Stream Redirection Utility<a class="anchor-link" href="python-network-scripting-pp4e.html#A-Stream-Redirection-Utility">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>even when line buffering is requested, socket wrapper file writes (and
by association, prints) are buffered until the program exits, manual flushes are reques-
ted, or the buffer becomes full.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># socket-unbuff-server.py</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">print_function</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>           <span class="c1"># read three messages over a raw socket</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">()</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="s1">''</span><span class="p">,</span> <span class="mi">60000</span><span class="p">))</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'accepting...'</span><span class="p">)</span>
<span class="n">conn</span><span class="p">,</span> <span class="nb">id</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>       <span class="c1"># blocks till client connect</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="s1">'receiving...'</span><span class="p">)</span>
    <span class="n">msg</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>      <span class="c1"># blocks till data received</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>                 <span class="c1"># gets all print lines at once unless flushed</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># socket-unbuff-client.py</span>
<span class="c1"># send three msgs over wrapped and raw socket</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">print_function</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">()</span>                        <span class="c1"># default=AF_INET, SOCK_STREAM (tcp/ip)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="mi">60000</span><span class="p">))</span>
<span class="c1"># default=full buff, 0=error, 1 not linebuff!</span>
<span class="n">file</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">makefile</span><span class="p">(</span><span class="s1">'w'</span><span class="p">,</span> <span class="n">buffering</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="s1">'sending data1'</span><span class="p">)</span>
<span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'spam</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>               <span class="c1"># must follow with flush() to truly send now</span>
<span class="c1"># file.flush()               # uncomment flush lines to see the difference</span>

<span class="nb">print</span><span class="p">(</span><span class="s1">'sending data2'</span><span class="p">)</span>
<span class="c1"># adding more file prints does not flush buffer either</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'eggs'</span><span class="p">,</span> <span class="n">file</span><span class="p">)</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="c1"># file.flush()               # output appears at server recv only upon</span>
<span class="c1"># flush or exit</span>

<span class="nb">print</span><span class="p">(</span><span class="s1">'sending data3'</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s1">'ham</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>         <span class="c1"># low-level byte string interface sends immediately</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>               <span class="c1"># received first if don't flush other two!</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Buffering-in-other-contexts:-Command-pipes-revisited">Buffering in other contexts: Command pipes revisited<a class="anchor-link" href="python-network-scripting-pp4e.html#Buffering-in-other-contexts:-Command-pipes-revisited">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Buffered streams and deadlock are general issues that go beyond
socket wrapper files.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># pipe-unbuff-writer.py</span>
<span class="c1"># output line buffered (unbuffered) if stdout is a terminal, buffered by default for</span>
<span class="c1"># other devices: use -u or sys.stdout.flush() to avoid delayed output on pipe/socket</span>
<span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">sys</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">asctime</span><span class="p">())</span>                 <span class="c1"># print transfers per stream buffering</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'spam</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>            <span class="c1"># ditto for direct stream file access</span>
    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>                         <span class="c1"># unles sys.stdout reset to other file</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># no output for 10 seconds unless Python -u flag used or sys.stdout.flush()</span>
<span class="c1"># but writer's output appears here every 2 seconds when either option is used</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">print_function</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">popen</span><span class="p">(</span><span class="s1">'python -u pipe-unbuff-writer.py'</span><span class="p">):</span>    <span class="c1"># iterator reads lines</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">line</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>                                     <span class="c1"># blocks without -u!</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Sockets-versus-command-pipes">Sockets versus command pipes<a class="anchor-link" href="python-network-scripting-pp4e.html#Sockets-versus-command-pipes">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>why use sockets in this redirection role at all? Programs require a direct spawning relationship, command pipes do not support longerlived or remotely running servers the way that sockets do.</p>
<ul>
<li>With sockets, we can start client and server independently, and the server may continue
running perpetually to serve multiple clients (albeit with some changes to our utility
module’s listener initialization code). Moreover, passing in remote machine names to
our socket redirection tools would allow a client to connect to a server running on a
completely different machine.</li>
<li>named pipes (fifos) accessed
with the open call support stronger independence of client and server, too, but unlike
sockets, they are usually limited to the local machine, and are not supported on all
platforms.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="A-Simple-Python-File-Server">A Simple Python File Server<a class="anchor-link" href="python-network-scripting-pp4e.html#A-Simple-Python-File-Server">¶</a>
</h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>implements both the server-side and the client-side
logic needed to ship a requested file from server to client machines over a raw socket.</p>
<p>implement client and server-side logic to transfer an arbitrary file from
server to client over a socket; uses a simple control-info protocol rather
than separate sockets for control and data (as in ftp), dispatches each
client request to a handler thread, and loops to transfer the entire file
by blocks; see ftplib examples for a higher-level transport scheme</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [6]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="sd">"""</span>
<span class="sd">#############################################################################</span>
<span class="sd">implement client and server-side logic to transfer an arbitrary file from</span>
<span class="sd">server to client over a socket; uses a simple control-info protocol rather</span>
<span class="sd">than separate sockets for control and data (as in ftp), dispatches each</span>
<span class="sd">client request to a handler thread, and loops to transfer the entire file</span>
<span class="sd">by blocks; see ftplib examples for a higher-level transport scheme;</span>
<span class="sd">#############################################################################</span>
<span class="sd">"""</span>

<span class="kn">import</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">thread</span>
<span class="kn">from</span> <span class="nn">socket</span> <span class="k">import</span> <span class="o">*</span>

<span class="n">blksz</span> <span class="o">=</span> <span class="mi">1024</span>
<span class="n">defaultHost</span> <span class="o">=</span> <span class="s1">'localhost'</span>
<span class="n">defaultPort</span> <span class="o">=</span> <span class="mi">50001</span>

<span class="n">helptext</span> <span class="o">=</span> <span class="s2">"""</span>
<span class="s2">Usage...</span>
<span class="s2">server=&gt; getfile.py  -mode server            [-port nnn] [-host hhh|localhost]</span>
<span class="s2">client=&gt; getfile.py [-mode client] -file fff [-port nnn] [-host hhh|localhost]</span>
<span class="s2">"""</span>

<span class="k">def</span> <span class="nf">now</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">asctime</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">parsecommandline</span><span class="p">():</span>
    <span class="nb">dict</span> <span class="o">=</span> <span class="p">{}</span>                        <span class="c1"># put in dictionary for easy lookup</span>
    <span class="n">args</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>              <span class="c1"># skip program name at front of args</span>
    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">:</span>            <span class="c1"># example: dict['-mode'] = 'server'</span>
        <span class="nb">dict</span><span class="p">[</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="n">args</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">2</span><span class="p">:]</span>
    <span class="k">return</span> <span class="nb">dict</span>

<span class="k">def</span> <span class="nf">client</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
    <span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">send</span><span class="p">((</span><span class="n">filename</span> <span class="o">+</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>      <span class="c1"># send remote name with dir: bytes</span>
    <span class="n">dropdir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">filename</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>       <span class="c1"># filename at end of dir path</span>
    <span class="n">file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">dropdir</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span>                 <span class="c1"># create local file in cwd</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="n">blksz</span><span class="p">)</span>                <span class="c1"># get up to 1K at a time</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span> <span class="k">break</span>                     <span class="c1"># till closed on server side</span>
        <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>                       <span class="c1"># store data in local file</span>
    <span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
    <span class="n">file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
    <span class="nb">print</span><span class="p">(</span><span class="s1">'Client got'</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="s1">'at'</span><span class="p">,</span> <span class="n">now</span><span class="p">())</span>

<span class="k">def</span> <span class="nf">serverthread</span><span class="p">(</span><span class="n">clientsock</span><span class="p">):</span>
    <span class="n">sockfile</span> <span class="o">=</span> <span class="n">clientsock</span><span class="o">.</span><span class="n">makefile</span><span class="p">(</span><span class="s1">'r'</span><span class="p">)</span>        <span class="c1"># wrap socket in dup file obj</span>
    <span class="n">filename</span> <span class="o">=</span> <span class="n">sockfile</span><span class="o">.</span><span class="n">readline</span><span class="p">()[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>        <span class="c1"># get filename up to end-line</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">file</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">)</span>
        <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
            <span class="nb">bytes</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">blksz</span><span class="p">)</span>           <span class="c1"># read/send 1K at a time</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="nb">bytes</span><span class="p">:</span> <span class="k">break</span>                <span class="c1"># until file totally sent</span>
            <span class="n">sent</span> <span class="o">=</span> <span class="n">clientsock</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="nb">bytes</span><span class="p">)</span>
            <span class="k">assert</span> <span class="n">sent</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="nb">bytes</span><span class="p">)</span>
    <span class="k">except</span><span class="p">:</span>
        <span class="nb">print</span> <span class="s1">'Error downloading file on server:'</span><span class="p">,</span> <span class="n">filename</span>
    <span class="n">clientsock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">server</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">):</span>
    <span class="n">serversock</span> <span class="o">=</span> <span class="n">socket</span><span class="p">(</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">SOCK_STREAM</span><span class="p">)</span>     <span class="c1"># listen on TCP/IP socket</span>
    <span class="n">serversock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>                 <span class="c1"># serve clients in threads</span>
    <span class="n">serversock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">clientsock</span><span class="p">,</span> <span class="n">clientaddr</span> <span class="o">=</span> <span class="n">serversock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
        <span class="nb">print</span> <span class="s1">'Server connected by'</span><span class="p">,</span> <span class="n">clientaddr</span><span class="p">,</span> <span class="s1">'at'</span><span class="p">,</span> <span class="n">now</span><span class="p">()</span>
        <span class="n">thread</span><span class="o">.</span><span class="n">start_new_thread</span><span class="p">(</span><span class="n">serverthread</span><span class="p">,</span> <span class="p">(</span><span class="n">clientsock</span><span class="p">,))</span>

<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
    <span class="n">host</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'-host'</span><span class="p">,</span> <span class="n">defaultHost</span><span class="p">)</span>         <span class="c1"># use args or defaults</span>
    <span class="n">port</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'-port'</span><span class="p">,</span> <span class="n">defaultPort</span><span class="p">))</span>    <span class="c1"># is a string in argv</span>
    <span class="k">if</span> <span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'-mode'</span><span class="p">)</span> <span class="o">==</span> <span class="s1">'server'</span><span class="p">:</span>             <span class="c1"># None if no -mode: client</span>
        <span class="k">if</span> <span class="n">host</span> <span class="o">==</span> <span class="s1">'localhost'</span><span class="p">:</span> <span class="n">host</span> <span class="o">=</span> <span class="s1">''</span>         <span class="c1"># else fails remotely</span>
        <span class="n">server</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
    <span class="k">elif</span> <span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'-file'</span><span class="p">):</span>                       <span class="c1"># client mode needs -file</span>
        <span class="n">client</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">args</span><span class="p">[</span><span class="s1">'-file'</span><span class="p">])</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="nb">print</span> <span class="n">helptext</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
    <span class="n">args</span> <span class="o">=</span> <span class="n">parsecommandline</span><span class="p">()</span>
    <span class="n">main</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ol>
<li>The server function farms out each incoming client request to a thread that trans-
fers the requested file’s bytes.</li>
<li>The client function sends the server a file’s name and stores all the bytes it gets
back in a local file of the same name.</li>
<li>The most novel feature here is the protocol between client and server: the client starts
the conversation by shipping a filename string up to the server, terminated with an end-
of-line character, and including the file’s directory path in the server. At the server, a
spawned thread extracts the requested file’s name by reading the client socket, and
opens and transfers the requested file back to the client, one chunk of bytes at a time.</li>
</ol>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Running-the-File-Server-and-Clients">Running the File Server and Clients<a class="anchor-link" href="python-network-scripting-pp4e.html#Running-the-File-Server-and-Clients">¶</a>
</h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>One subtle security point here: the server instance code is happy to send any server-
side file whose pathname is sent from a client, as long as the server is run with a user-
name that has read access to the requested file. If you care about keeping some of your
server-side files private, you should add logic to suppress downloads of restricted files.
I’ll leave this as a suggested exercise here, but we will implement such filename checks
in a different getfile download tool later in this book.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h4 id="Adding-a-User-Interface-Frontend">Adding a User-Interface Frontend<a class="anchor-link" href="python-network-scripting-pp4e.html#Adding-a-User-Interface-Frontend">¶</a>
</h4>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>For instance, it would be easy to implement a simple tkinter GUI frontend to the client-
side portion of the getfile script we just met. Such a tool, run on the client machine,
may simply pop up a window with Entry widgets for typing the desired filename, server,
and so on. Once download parameters have been input, the user interface could either
import and call the getfile.client function with appropriate option arguments, or
build and run the implied getfile.py command line using tools such as os.system ,
os.popen , subprocess , and so on.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h5 id="Using-row-frames-and-command-lines">Using row frames and command lines<a class="anchor-link" href="python-network-scripting-pp4e.html#Using-row-frames-and-command-lines">¶</a>
</h5>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="sd">"""</span>
<span class="sd">launch getfile script client from simple tkinter GUI;</span>
<span class="sd">could also use os.fork+exec, os.spawnv (see Launcher);</span>
<span class="sd">windows: replace 'python' with 'start' if not on path;</span>
<span class="sd">"""</span>

<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">tkinter</span> <span class="k">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">tkinter.messagebox</span> <span class="k">import</span> <span class="n">showinfo</span>
<span class="k">def</span> <span class="nf">onReturnKey</span><span class="p">():</span>
    <span class="n">cmdline</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'python getfile.py -mode client -file </span><span class="si">%s</span><span class="s1"> -port </span><span class="si">%s</span><span class="s1"> -host </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span>
                      <span class="p">(</span><span class="n">content</span><span class="p">[</span><span class="s1">'File'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">(),</span>
                       <span class="n">content</span><span class="p">[</span><span class="s1">'Port'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">(),</span>
                       <span class="n">content</span><span class="p">[</span><span class="s1">'Server'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">()))</span>
    <span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="n">cmdline</span><span class="p">)</span>
    <span class="n">showinfo</span><span class="p">(</span><span class="s1">'getfilegui-1'</span><span class="p">,</span> <span class="s1">'Download complete'</span><span class="p">)</span>

<span class="n">box</span> <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
<span class="n">labels</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'Server'</span><span class="p">,</span> <span class="s1">'Port'</span><span class="p">,</span> <span class="s1">'File'</span><span class="p">]</span>
<span class="n">content</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">label</span> <span class="ow">in</span> <span class="n">labels</span><span class="p">:</span>
    <span class="n">row</span> <span class="o">=</span> <span class="n">Frame</span><span class="p">(</span><span class="n">box</span><span class="p">)</span>
    <span class="n">row</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">fill</span><span class="o">=</span><span class="n">X</span><span class="p">)</span>
    <span class="n">Label</span><span class="p">(</span><span class="n">row</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="n">label</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mi">6</span><span class="p">)</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">LEFT</span><span class="p">)</span>
    <span class="n">entry</span> <span class="o">=</span> <span class="n">Entry</span><span class="p">(</span><span class="n">row</span><span class="p">)</span>
    <span class="n">entry</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">RIGHT</span><span class="p">,</span> <span class="n">expand</span><span class="o">=</span><span class="n">YES</span><span class="p">,</span> <span class="n">fill</span><span class="o">=</span><span class="n">X</span><span class="p">)</span>
    <span class="n">content</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="n">entry</span>

<span class="n">box</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'getfilegui-1'</span><span class="p">)</span>
<span class="n">box</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="s1">'&lt;Return&gt;'</span><span class="p">,</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">event</span><span class="p">:</span> <span class="n">onReturnKey</span><span class="p">()))</span>
<span class="n">mainloop</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h5 id="Using-grids-and-function-calls">Using grids and function calls<a class="anchor-link" href="python-network-scripting-pp4e.html#Using-grids-and-function-calls">¶</a>
</h5>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="sd">"""</span>
<span class="sd">same, but with grids and import+call, not packs and cmdline;</span>
<span class="sd">direct function calls are usually faster than running files;</span>
<span class="sd">"""</span>

<span class="kn">import</span> <span class="nn">getfile</span>
<span class="kn">from</span> <span class="nn">tkinter</span> <span class="k">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">tkinter.messagebox</span> <span class="k">import</span> <span class="n">showinfo</span>

<span class="k">def</span> <span class="nf">onSubmit</span><span class="p">():</span>
    <span class="n">getfile</span><span class="o">.</span><span class="n">client</span><span class="p">(</span><span class="n">content</span><span class="p">[</span><span class="s1">'Server'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">(),</span>
                   <span class="nb">int</span><span class="p">(</span><span class="n">content</span><span class="p">[</span><span class="s1">'Port'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">()),</span>
                   <span class="n">content</span><span class="p">[</span><span class="s1">'File'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">())</span>
    <span class="n">showinfo</span><span class="p">(</span><span class="s1">'getfilegui-2'</span><span class="p">,</span> <span class="s1">'Download complete'</span><span class="p">)</span>

<span class="n">box</span>    <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
<span class="n">labels</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'Server'</span><span class="p">,</span> <span class="s1">'Port'</span><span class="p">,</span> <span class="s1">'File'</span><span class="p">]</span>
<span class="n">rownum</span>  <span class="o">=</span> <span class="mi">0</span>
<span class="n">content</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">label</span> <span class="ow">in</span> <span class="n">labels</span><span class="p">:</span>
    <span class="n">Label</span><span class="p">(</span><span class="n">box</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="n">label</span><span class="p">)</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="n">column</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">row</span><span class="o">=</span><span class="n">rownum</span><span class="p">)</span>
    <span class="n">entry</span> <span class="o">=</span> <span class="n">Entry</span><span class="p">(</span><span class="n">box</span><span class="p">)</span>
    <span class="n">entry</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="n">column</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">row</span><span class="o">=</span><span class="n">rownum</span><span class="p">,</span> <span class="n">sticky</span><span class="o">=</span><span class="n">E</span><span class="o">+</span><span class="n">W</span><span class="p">)</span>
    <span class="n">content</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="n">entry</span>
    <span class="n">rownum</span> <span class="o">+=</span> <span class="mi">1</span>

<span class="n">box</span><span class="o">.</span><span class="n">columnconfigure</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>   <span class="c1"># make expandable</span>
<span class="n">box</span><span class="o">.</span><span class="n">columnconfigure</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">weight</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="s1">'Submit'</span><span class="p">,</span> <span class="n">command</span><span class="o">=</span><span class="n">onSubmit</span><span class="p">)</span><span class="o">.</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span><span class="o">=</span><span class="n">rownum</span><span class="p">,</span> <span class="n">column</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">columnspan</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>

<span class="n">box</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'getfilegui-2'</span><span class="p">)</span>
<span class="n">box</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="s1">'&lt;Return&gt;'</span><span class="p">,</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">event</span><span class="p">:</span> <span class="n">onSubmit</span><span class="p">()))</span>
<span class="n">mainloop</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h5 id="Using-a-reusable-form-layout-class">Using a reusable form-layout class<a class="anchor-link" href="python-network-scripting-pp4e.html#Using-a-reusable-form-layout-class">¶</a>
</h5>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>If you’re like me, though, writing all the GUI form layout code in those two scripts can
seem a bit tedious, whether you use packing or grids. In fact, it became so tedious to
me that I decided to write a general-purpose form-layout class, shown in Exam-
ple 12-20, which handles most of the GUI layout grunt work.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="sd">"""</span>
<span class="sd">##################################################################</span>
<span class="sd">a reusable form class, used by getfilegui (and others)</span>
<span class="sd">##################################################################</span>
<span class="sd">"""</span>

<span class="kn">from</span> <span class="nn">tkinter</span> <span class="k">import</span> <span class="o">*</span>
<span class="n">entrysize</span> <span class="o">=</span> <span class="mi">40</span>

<span class="k">class</span> <span class="nc">Form</span><span class="p">:</span>                                           <span class="c1"># add non-modal form box</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">labels</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>          <span class="c1"># pass field labels list</span>
        <span class="n">labelsize</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">labels</span><span class="p">)</span> <span class="o">+</span> <span class="mi">2</span>
        <span class="n">box</span> <span class="o">=</span> <span class="n">Frame</span><span class="p">(</span><span class="n">parent</span><span class="p">)</span>                           <span class="c1"># box has rows, buttons</span>
        <span class="n">box</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">expand</span><span class="o">=</span><span class="n">YES</span><span class="p">,</span> <span class="n">fill</span><span class="o">=</span><span class="n">X</span><span class="p">)</span>                  <span class="c1"># rows has row frames</span>
        <span class="n">rows</span> <span class="o">=</span> <span class="n">Frame</span><span class="p">(</span><span class="n">box</span><span class="p">,</span> <span class="n">bd</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">relief</span><span class="o">=</span><span class="n">GROOVE</span><span class="p">)</span>        <span class="c1"># go=button or return key</span>
        <span class="n">rows</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">TOP</span><span class="p">,</span> <span class="n">expand</span><span class="o">=</span><span class="n">YES</span><span class="p">,</span> <span class="n">fill</span><span class="o">=</span><span class="n">X</span><span class="p">)</span>       <span class="c1"># runs onSubmit method</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="n">label</span> <span class="ow">in</span> <span class="n">labels</span><span class="p">:</span>
            <span class="n">row</span> <span class="o">=</span> <span class="n">Frame</span><span class="p">(</span><span class="n">rows</span><span class="p">)</span>
            <span class="n">row</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">fill</span><span class="o">=</span><span class="n">X</span><span class="p">)</span>
            <span class="n">Label</span><span class="p">(</span><span class="n">row</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="n">label</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="n">labelsize</span><span class="p">)</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">LEFT</span><span class="p">)</span>
            <span class="n">entry</span> <span class="o">=</span> <span class="n">Entry</span><span class="p">(</span><span class="n">row</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="n">entrysize</span><span class="p">)</span>
            <span class="n">entry</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">RIGHT</span><span class="p">,</span> <span class="n">expand</span><span class="o">=</span><span class="n">YES</span><span class="p">,</span> <span class="n">fill</span><span class="o">=</span><span class="n">X</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">content</span><span class="p">[</span><span class="n">label</span><span class="p">]</span> <span class="o">=</span> <span class="n">entry</span>
        <span class="n">Button</span><span class="p">(</span><span class="n">box</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s1">'Cancel'</span><span class="p">,</span> <span class="n">command</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">onCancel</span><span class="p">)</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">RIGHT</span><span class="p">)</span>
        <span class="n">Button</span><span class="p">(</span><span class="n">box</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s1">'Submit'</span><span class="p">,</span> <span class="n">command</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">onSubmit</span><span class="p">)</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span><span class="o">=</span><span class="n">RIGHT</span><span class="p">)</span>
        <span class="n">box</span><span class="o">.</span><span class="n">master</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="s1">'&lt;Return&gt;'</span><span class="p">,</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">event</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">onSubmit</span><span class="p">()))</span>

    <span class="k">def</span> <span class="nf">onSubmit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>                                      <span class="c1"># override this</span>
        <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span><span class="p">:</span>                             <span class="c1"># user inputs in</span>
            <span class="nb">print</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s1">'</span><span class="se">\t</span><span class="s1">=&gt;</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">())</span>    <span class="c1"># self.content[k]</span>

    <span class="k">def</span> <span class="nf">onCancel</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>                                      <span class="c1"># override if need</span>
        <span class="n">Tk</span><span class="p">()</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>                                          <span class="c1"># default is exit</span>

<span class="k">class</span> <span class="nc">DynamicForm</span><span class="p">(</span><span class="n">Form</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">labels</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="n">labels</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'Enter field names: '</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
        <span class="n">Form</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">onSubmit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">'Field values...'</span><span class="p">)</span>
        <span class="n">Form</span><span class="o">.</span><span class="n">onSubmit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">onCancel</span><span class="p">()</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
    <span class="kn">import</span> <span class="nn">sys</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">Form</span><span class="p">([</span><span class="s1">'Name'</span><span class="p">,</span> <span class="s1">'Age'</span><span class="p">,</span> <span class="s1">'Job'</span><span class="p">])</span>     <span class="c1"># precoded fields, stay after submit</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">DynamicForm</span><span class="p">()</span>                    <span class="c1"># input fields, go away after submit</span>
    <span class="n">mainloop</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="prompt input_prompt">In [ ]:</div>
<div class="inner_cell">
    <div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="sd">"""</span>
<span class="sd">launch getfile client with a reusable GUI form class;</span>
<span class="sd">os.chdir to target local dir if input (getfile stores in cwd);</span>
<span class="sd">to do: use threads, show download status and getfile prints;</span>
<span class="sd">"""</span>

<span class="kn">from</span> <span class="nn">form</span> <span class="k">import</span> <span class="n">Form</span>
<span class="kn">from</span> <span class="nn">tkinter</span> <span class="k">import</span> <span class="n">Tk</span><span class="p">,</span> <span class="n">mainloop</span>
<span class="kn">from</span> <span class="nn">tkinter.messagebox</span> <span class="k">import</span> <span class="n">showinfo</span>
<span class="kn">import</span> <span class="nn">getfile</span><span class="o">,</span> <span class="nn">os</span>

<span class="k">class</span> <span class="nc">GetfileForm</span><span class="p">(</span><span class="n">Form</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">oneshot</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
        <span class="n">root</span> <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
        <span class="n">root</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">'getfilegui'</span><span class="p">)</span>
        <span class="n">labels</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'Server Name'</span><span class="p">,</span> <span class="s1">'Port Number'</span><span class="p">,</span> <span class="s1">'File Name'</span><span class="p">,</span> <span class="s1">'Local Dir?'</span><span class="p">]</span>
        <span class="n">Form</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">labels</span><span class="p">,</span> <span class="n">root</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">oneshot</span> <span class="o">=</span> <span class="n">oneshot</span>

    <span class="k">def</span> <span class="nf">onSubmit</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">Form</span><span class="o">.</span><span class="n">onSubmit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="n">localdir</span>   <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span><span class="p">[</span><span class="s1">'Local Dir?'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
        <span class="n">portnumber</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span><span class="p">[</span><span class="s1">'Port Number'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
        <span class="n">servername</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span><span class="p">[</span><span class="s1">'Server Name'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
        <span class="n">filename</span>   <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">content</span><span class="p">[</span><span class="s1">'File Name'</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">localdir</span><span class="p">:</span>
            <span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">localdir</span><span class="p">)</span>
        <span class="n">portnumber</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">portnumber</span><span class="p">)</span>
        <span class="n">getfile</span><span class="o">.</span><span class="n">client</span><span class="p">(</span><span class="n">servername</span><span class="p">,</span> <span class="n">portnumber</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>
        <span class="n">showinfo</span><span class="p">(</span><span class="s1">'getfilegui'</span><span class="p">,</span> <span class="s1">'Download complete'</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">oneshot</span><span class="p">:</span> <span class="n">Tk</span><span class="p">()</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>  <span class="c1"># else stay in last localdir</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">'__main__'</span><span class="p">:</span>
    <span class="n">GetfileForm</span><span class="p">()</span>
    <span class="n">mainloop</span><span class="p">()</span>
</pre></div>

</div>
</div>
</div>

</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>One caveat worth pointing out here: the GUI is essentially dead while the download is
in progress (even screen redraws aren’t handled—try covering and uncovering the
window and you’ll see what I mean). We could make this better by running the down-
load in a thread, but since we’ll see how to do that in the next chapter when we explore
the FTP protocol, you should consider this problem a preview.</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In
particular, getfile clients can talk only to machines that are running a getfile server.
In the next chapter, we’ll discover another way to download files—FTP—which also
runs on sockets but provides a higher-level interface and is available as a standard
service on many machines on the Net. We don’t generally need to start up a custom
server to transfer files over FTP, the way we do with getfile . In fact, the user-interface
scripts in this chapter could be easily changed to fetch the desired file with Python’s
FTP tools, instead of the getfile module. But instead of spilling all the beans here, I’ll
just say, “Read on.”</p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Using-Serial-Ports">Using Serial Ports<a class="anchor-link" href="python-network-scripting-pp4e.html#Using-Serial-Ports">¶</a>
</h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered">
<div class="prompt input_prompt">
</div>
<div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>If you’re looking for a lower-level way to communicate with devices in general, though,
you may also be interested in the topic of Python’s serial port interfaces. This isn’t quite
related to Internet scripting, but it’s similar enough in spirit and is discussed often
enough on the Net to merit a few words here.</p>
<p>In brief, scripts can use serial port interfaces to engage in low-level communication with
things like mice, modems, and a wide variety of serial devices and hardware. Serial port
interfaces are also used to communicate with devices connected over infrared ports
(e.g., hand-held computers and remote modems). Such interfaces let scripts tap into
raw data streams and implement device protocols of their own. Other Python tools
such as the ctypes and struct modules may provide additional tools for creating and
extracting the packed binary data these ports transfer.</p>
<p>At this writing, there are a variety of ways to send and receive data over serial ports in
Python scripts. Notable among these options is an open source extension package
known as pySerial, which allows Python scripts to control serial ports on both Windows
and Linux, as well as BSD Unix, Jython (for Java), and IronPython (for .Net and Mono).
Unfortunately, there is not enough space to cover this or any other serial port option
in any sort of detail in this text. As always, see your favorite web search engine for up-
to-date details on this front.</p>

</div>
</div>
</div>
    </div>
  </div>

    </div>
    <aside class="postpromonav"><nav><ul itemprop="keywords" class="tags">
<li><a class="tag p-category" href="../categories/chs.html" rel="tag">CHS</a></li>
            <li><a class="tag p-category" href="../categories/ipython.html" rel="tag">ipython</a></li>
            <li><a class="tag p-category" href="../categories/other.html" rel="tag">Other</a></li>
            <li><a class="tag p-category" href="../categories/python.html" rel="tag">Python</a></li>
        </ul>
<ul class="pager hidden-print">
<li class="previous">
                <a href="introduction-to-julia.html" rel="prev" title="introduction-to-julia">Previous post</a>
            </li>
            <li class="next">
                <a href="kivy-ch5-remote-desktop-app.html" rel="next" title="kivy-ch5-remote-desktop-app">Next post</a>
            </li>
        </ul></nav></aside><script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> </script><script type="text/x-mathjax-config">
MathJax.Hub.Config({
    tex2jax: {
        inlineMath: [ ['$','$'], ["\\(","\\)"] ],
        displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
        processEscapes: true
    },
    displayAlign: 'center', // Change this to 'center' to center equations.
    "HTML-CSS": {
        styles: {'.MathJax_Display': {"margin": 0}}
    }
});
</script></article>
</div>
        <!--End of body content-->

        <footer id="footer">
            Contents © 2017         <a href="mailto:muxuezi@gmail.com">Tao Junjie</a> - Powered by         <a href="https://getnikola.com" rel="nofollow">Nikola</a>         
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0">
<img alt="Creative Commons License BY-NC-SA" style="border-width:0; margin-bottom:12px;" src="http://i.creativecommons.org/l/by-nc-sa/4.0/80x15.png"></a>
            
        </footer>
</div>
</div>


            <script src="../assets/js/all-nocdn.js"></script><script>$('a.image-reference:not(.islink) img:not(.islink)').parent().colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script><!-- fancy dates --><script>
    moment.locale("en");
    fancydates(0, "YYYY-MM-DD HH:mm");
    </script><!-- end fancy dates --><script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-51330059-1', 'auto');
  ga('send', 'pageview');

</script>
</body>
</html>
